home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Network Support Library
/
RoseWare - Network Support Library.iso
/
manage
/
gtree.arc
/
GTREE.C
next >
Wrap
C/C++ Source or Header
|
1988-03-17
|
14KB
|
392 lines
/**********************************************************************/
/* */
/* GTREE.C */
/* */
/* This will search an entire drive and print a graphical picture */
/* of the tree structure of its directories. */
/* */
/**********************************************************************/
/* */
/* Written October 21, 1985 */
/* */
/* Author David Midkiff -- D. M. Software And Systems */
/* */
/**********************************************************************/
/* */
/* Modified December 13, 1986 */
/* David Midkiff -- D. M. Software And Systems */
/* Added the ability to delete the specified files. */
/* */
/**********************************************************************/
/* */
/* Modified January 29, 1987 */
/* David Midkiff -- D. M. Software And Systems */
/* Changed the delete function to ask for operator */
/* verification beforing deleting files, and the -v */
/* command line switch to "pre"-verify deletions. */
/* */
/**********************************************************************/
/* */
/* Modified December 1, 1987 */
/* David Midkiff -- D. M. Software And Systems */
/* This code was ported from the Lattice C compiler to */
/* Turbo C. */
/* */
/**********************************************************************/
/* */
/* Modified December 23, 1987 */
/* David Midkiff -- D. M. Software And Systems */
/* This was becoming unmanagable and unusable, so I */
/* took the code from HUNT.C and moved it to here so I */
/* could just print a reasonable tree and created two */
/* programs from HUNT. These are GTREE and HUNT. */
/* */
/**********************************************************************/
/* */
/* Copyright (c) 1988 -- D. M. Software And Systems */
/* */
/* All rights reserved. Do not redistribute this program without */
/* this notice, or the notice in the main() function. */
/* */
/* This program is designed to be instructive and useful, however */
/* there are no warranties expressed or implied. Feel free to */
/* use this program in any manner you see fit, with the exceptions */
/* of commerical environments and redistribution for any fee. */
/* You are feel free to redistribute this program to any bulletin */
/* boards or user's group, provide no fee is charge for any service */
/* you may provide. */
/* */
/* If you find this program useful, you are asked to send a $20 */
/* contribution towards its upkeep. No support will be given to */
/* unsupported users, except in the cases where the user needs to */
/* find out if this program is suitable for his or her purposes. */
/* */
/* Send $20.00 contribution to: */
/* D. M. Software And Systems */
/* 6572 Suson Woods Drive */
/* St. Louis, MO 63128 */
/* */
/* Remember, you do not have to send a contribution, but your */
/* conscience will haunt you forever. */
/* */
/**********************************************************************/
#include "stdio.h"
#include "conio.h"
#include "ctype.h"
#include "dir.h"
#include "dos.h"
#include "io.h"
#include "stdlib.h"
#include "string.h"
extern unsigned _stklen = 32678U ; /* Need a larger than normal stack */
/* since buildtree() is recursive. */
/*PAGE*/
/*******************************************************/
/* */
/* --- GLOBAL VARIABLE DEFINITIONS --- */
/* */
/*******************************************************/
static int lenflags[21] = /* Length of each level's name */
{ 4 } ; /* Root name's length */
static int moreflags[21] ; /* 1 == Level has more to print */
struct DIRDATA {
char name[65] ; /* Directory's entire path name */
char thisname[65] ; /* This directory's name */
struct DIRDATA *list ; /* Beginning of list for this level */
struct DIRDATA *next ; /* Pointer to nest directory */
struct DIRDATA *node ; /* Pointer to previous node level */
int level ; /* How deeply nested we are with this directory */
} ;
char corner = '┐' ; /* Corner character for line drawings */
int drive = -1 ; /* Drive to use as a default */
char horizontal_line = '─' ; /* Horizontal line character for line drawings */
char left_chr = '├' ; /* For when a level is continued */
char left_corner = '└' ; /* For the last file in a level */
#define NSP (struct DIRDATA *) 0 /* Null Structure pointer for DIRDATA */
struct DIRDATA root ; /* For the root directory */
char scratch[256] ; /* A scratch string */
#define SPACE ' ' /* A space character */
char vertical_line = '│' ; /* Vertical line character for line drawings */
/*PAGE*/
/***********************************/
/* */
/* FUNCTION PROTOTYPES */
/* */
/***********************************/
void buildtree( struct DIRDATA *thisdirectory ) ;
void fatalerr( char *message , int useflag ) ;
void print_tree( struct DIRDATA *pointlist ) ;
void showusage( void ) ;
void strupper( char *destination , char *source ) ;
/*PAGE*/
/**********************************************************************/
/* */
/* BUILDTREE() - Build a directory tree from the passed name. */
/* Care should be used when changing this */
/* routine!!!! It works as it stands now. */
/* */
/**********************************************************************/
void buildtree( p )
struct DIRDATA *p ; /* Directory being searched */
{
struct ffblk dir ; /* For a directories information */
static int nestedlevel = 0 ; /* How deeply nested we are */
struct DIRDATA *new ; /* For any directory found */
char newname[81] ; /* String for formatting a name */
struct DIRDATA *t ; /* A scratch pointer */
static int lastlevel = 0 ; /* Last level with a file added */
static struct DIRDATA *lastone = &root ;
(void) sprintf( newname , "%s*.*" , p->name ) ;
if( !findfirst( newname , &dir , FA_DIREC ) )
{
do
{
if( dir.ff_attrib == FA_DIREC && dir.ff_name[0] != '.' )
{
(void) sprintf( newname , "%s%s\\" , p->name , dir.ff_name ) ;
if( (new=malloc((unsigned)sizeof(struct DIRDATA))) == NULL )
fatalerr( "Out of memory during tree allocation" , 0 ) ;
/***************************************/
/* Initialize the new structure's data */
/***************************************/
new->node = new->list = new->next = NSP ;
new->level = nestedlevel ;
(void) strcpy( new->thisname , dir.ff_name ) ;
(void) strcpy( new->name , newname ) ;
if( nestedlevel > lastlevel ) /*****************************/
{ /* First file in a new level */
new->node = lastone ; /*****************************/
lastone->next = new ;
lastone = new ;
} /* if( nestedlevel > lastlevel ) */
if( nestedlevel == lastlevel ) /*****************************/
{ /* Next file in same level */
new->node = lastone ; /*****************************/
lastone->list = new ;
lastone = new ;
} /* if( nestedlevel == lastlevel ) */
if( nestedlevel < lastlevel ) /*****************************/
{ /* Back to a previous level */
t = lastone ; /*****************************/
while( t->level > nestedlevel )
t = t->node ;
while( t->list != NSP )
t = t->list ;
t->list = new ;
new->node = t ;
lastone = new ;
} /* if( nextedlevel < lastlevel ) */
lastlevel = nestedlevel++ ;
buildtree( new ) ;
} /* if( dir.ff_attrib == FA_DIREC && dir.ff_name[0] != '.' ) */
} while( !findnext( &dir ) ) ;
} /* if( !findfirst( newname , dir , FA_DIREC ) ) */
nestedlevel-- ;
return ;
} /* end of buildtree() */
/*PAGE*/
/**********************************************************************/
/* */
/* FATALERR() - Print a fatal error message and exit after setting */
/* the DOS ERRORLEVEL variable to 1. */
/* */
/**********************************************************************/
void fatalerr( msg , useflag )
char *msg ; /* Part of error message to print */
int useflag ; /* 1 == Show usage before exiting */
{
printf( "\n %s -- GTREE canceled\n" , msg ) ;
if( useflag )
showusage() ;
exit( 1 ) ;
return ; /* sic */
} /* end of fatal error */
/*page*/
/**********************************************************************/
/* */
/* MAIN() - This is the main processing function. The only things */
/* that are processed here are command line parameters. */
/* The process is: */
/* 1.) Process command line arguements. */
/* 2.) Check for a drive assignment. If not present */
/* use the default drive. */
/* 3.) Format the root file name by inserting the */
/* drive letter to give C:\, for example. */
/* 4.) Call the buildtree() function with the root */
/* directory to get started. */
/* */
/**********************************************************************/
void main( argc , argv )
int argc ;
char *argv[] ;
{
int i ; /* A scratch integer */
(void) puts( "GTREE -- Version 1.0 -- March 1988\nCopyright (c) 1988. D. M. Software and Systems. All rights reserved." ) ;
for( i=1; i<argc; i++ ) /* Parse the command line arguments */
{
if( *argv[i] != '-' && *argv[i] != '/' )
{
if( *(argv[i]+1) != ':' )
fatalerr( "Invalid command line switch" , 1 ) ;
else
drive = toupper( *argv[i] ) - 'A' ;
}
else
{
if( tolower( *(argv[i]+1) ) == 'g' )
{
left_corner = left_chr = corner = '+' ;
vertical_line = '|' ;
horizontal_line = '-' ;
}
else /* Invalid switch */
{
(void) sprintf( scratch , "%s is an invalid parameter" , argv[i] ) ;
fatalerr( scratch , 0 ) ;
} /* if( tolower( *(argv[i]+1) ) == 'g' ) */
} /* if( *argv[i] != '-' && *argv[i] != '/' ) */
} /* for( i=1; iargc; i++ ) */
if( drive == -1 ) /* Set drive to the current drive */
drive = getdisk() ; /* of not set by the operator. */
drive += 'A' ; /* Convert to alpha */
(void) sprintf( root.name , "%c:\\" , drive ) ; /* Format for buildtree()'s initial call */
root.level = 0 ;
root.node = root.next = root.list = NSP ;
buildtree( &root ) ;
if( root.next == NSP && root.list == NSP )
{
printf( "\n\nThere where no directories after %s" , root.name ) ;
return ;
} /* if( root->nest == NSP && root->list == NSP ) */
printf( "\n%s%c%c\n" , root.name , horizontal_line , corner ) ;
print_tree( root.list ) ;
exit( 0 ) ;
} /* end of main() */
/**********************************************************************/
/* */
/* PRINT_TREE() - This will print the tree. It is not part of the */
/* buildtree() function the grahpics characters that */
/* are used. There is a look ahead problem that is */
/* associated with all of the connectors. */
/* */
/* WARNING - This function, like buildtree() is */
/* recursive. Use care when changing. */
/* */
/**********************************************************************/
void print_tree( p )
struct DIRDATA *p ;
{
int i ; /* Scratch integer */
int j ; /* Scratch integer */
do
{
moreflags[p->level] = ( p->list != NSP ) ;
/***********************************************************/
/* Indent this line for each level and draw the connectors */
/* unless this is the current level or this one is empty. */
/***********************************************************/
for( i=0; i<=p->level; i++ )
{
for( j=0; j<lenflags[i]; j++ )
putchar( SPACE ) ;
if( i != p->level )
putchar( (moreflags[i]) ? vertical_line : SPACE ) ;
} /* for( i=0; i<=p->level; i++ ) */
printf( "%c%c%s" , (moreflags[p->level]!=0) ? left_chr : left_corner , horizontal_line , p->thisname ) ;
lenflags[p->level+1] = strlen( p->thisname ) + 2 ; /* Include line character */
/****************************************/
/* Is there another level from here ? */
/* If so, print a connector and call */
/* print_tree() again with the next one */
/****************************************/
if( p->next != NSP )
{
printf( "%c%c\n" , horizontal_line , corner ) ;
print_tree( p->next ) ;
} /* if( p->next != NSP ) */
else
(void) puts( "" ) ; /* Forced line feed */
p = p->list ;
} while( p != NSP ) ;
return ;
} /* end of print_tree() */
/**********************************************************************/
/* */
/* SHOWUSAGE() - Prints the usage message that appears at runtime. */
/* This will be called by certain errors from */
/* the fatalerr() routine above. */
/* */
/**********************************************************************/
void showusage()
{
(void) puts( "\nUsage is hunt [drive:] [-g] where:" ) ;
(void) puts( "\tdrive: overrides the default drive specification." ) ;
(void) puts( "\t-G for graphics. Suppresses graphics characters during display." ) ;
return ;
} /* end of showusage() */
/*************************/
/* */
/* END OF GTREE.C */
/* */
/*************************/